package server

import (
	"context"
	"fmt"
	"gbox-one-machine/conf"
	"gbox-one-machine/dao"
	"gbox-one-machine/discovery"
	"gbox-one-machine/log"
	"gbox-one-machine/services"
	"gbox-one-machine/utils"
	"github.com/gin-gonic/gin"
	"github.com/grandcat/zeroconf"
	"net/http"
)

// SlaveServer defination
type SlaveServer struct {
	httpSrv         *http.Server
	bonjourRegister *zeroconf.Server
	conf            *conf.Config
	oneMachine      *services.OneMachineService
}

// NewSlaveServer create http Slaveserver
func NewSlaveServer(ctx context.Context, cf *conf.Config) (*SlaveServer, error) {

	if cf.App.ENV == "prod" {
		gin.SetMode(gin.ReleaseMode)
	}
	//
	d, err := dao.New(cf.Dao)
	if err != nil {
		return nil, err
	}

	//ip, err := d.GetBoxIP(ctx)
	//if err != nil {
	//	return nil, err
	//}
	ip, mac, err := utils.ExternalIP()
	if err != nil {
		log.Logger.Errorf("GET LOCAL IP ERROR : %s", err)
	}
	params := []string{fmt.Sprintf("mac=%s", mac), "type=onemachine"}
	bonjourRegister, err := discovery.Register(ctx, cf.App.Name, ip.String(), cf.App.HTTPPort, params)
	if err != nil {
		return nil, err
	}
	log.Logger.Infof("bonjour registed %s %s %d %v", cf.App.Name, ip.String(), cf.App.HTTPPort, params)
	mux := gin.New()

	srv := &SlaveServer{
		httpSrv: &http.Server{
			Addr:    fmt.Sprintf(":%d", cf.App.HTTPPort),
			Handler: mux,
		},
		bonjourRegister: bonjourRegister,
		conf:            cf,
		oneMachine:      services.NewOneMachineService(cf, d),
	}

	mux.Use(
	//middleware.BaseMiddleware(cf),
	//middleware.SlaveMiddleware(),
	)

	mux.GET("/", func(c *gin.Context) { // for root check
		c.String(http.StatusOK, "slave node ok")
	})

	mux.GET("/api/v1/one_machine/bind", srv.oneMachine.Bind)

	return srv, nil
}

// Run Slaveserver
func (s *SlaveServer) Run() error {

	log.Logger.Info("HTTP Slaveserver starting...")

	if err := s.httpSrv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
		return err
	}

	log.Logger.Info("HTTP Slaveserver stoped")

	return nil
}

// Stop Slaveserver
func (s *SlaveServer) Stop() error {
	var errs error

	if err := s.httpSrv.Shutdown(conf.GetCtx()); err != nil && err != http.ErrServerClosed {
		errs = fmt.Errorf("%s\nHttp Slaveserver close err: %s", errs, err)
	}

	log.Logger.Info("HTTP Slaveserver Shutdown")

	s.bonjourRegister.Shutdown()

	log.Logger.Info("Bonjour Register Shutdown")

	if errs != nil {
		return errs
	}

	return nil
}
